Skip to main content

Webhook Event Example

This page shows the complete structure of events sent to your webhook

How often are events sent?

Events are sent in real-time as soon as the SDK detects a user entering a monitored area. Typical latency is a few seconds, depending on device connectivity.

Event sending works as follows:

  • Device entered the area of interest (monitored Cell ID), we send the EVENT_IN event
  • If the device remains in the area, we don't send new entry events within 24 hours.
  • When the event leaves the area and we have confirmation of this via the system, we will record this exit.
  • If the user returns to the area of the last configured cell_id, we will send the EVENT_IN again even if still within the 24-hour window.

Event Structure

When a user enters or leaves an area of interest, an event is sent via POST to your webhook endpoint in JSON format.

Complete Example

{
"mm": 1220290060,
"cell_id": "8881839825fffff",
"event_type": "EVENT_IN",
"event_duration": -1,
"created_at": 1767623650044,
"brand": "apple",
"model": "iPhone14,2",
"cfray": "55e5fg9e5ege4hgh-POA",
"origin": "beacon",
"adv_key": "com.grouplinknetwork.glconsumointeligente.sanasainteligente",
"os": "iOS",
"os_version": "26.1",
"package_name": "com.grouplinknetwork.glconsumointeligente.sanasainteligente"
}

Field Descriptions

Main Fields

FieldTypeDescriptionExample
mmnumberUnique mobile identifier (device ID hash)1220290060
cell_idstringH3 cell identifier where the event occurred"8881839825fffff"
event_typestringEvent type: EVENT_IN (entry)"EVENT_IN"
event_durationnumberEvent duration in milliseconds. -1 for entry events-1
created_atnumberUnix timestamp in milliseconds when the event was created1767623650044

Device Information

FieldTypeDescriptionExample
brandstringDevice brand"apple", "samsung", "xiaomi"
modelstringDevice model"iPhone14,2", "SM-G998B"
osstringDevice operating system"iOS", "Android"
os_versionstringOperating system version"26.1", "14.0"

Technical Fields

FieldTypeDescriptionExample
cfraystringCloudFlare tracking identifier (for debugging)"55e5fg9e5ege4hgh-POA"
originstringSignal origin: "beacon", "gps", "network""beacon"
adv_keystringAdvertising/beacon identification key"com.app.example"
package_namestringPackage name of the application that generated the event"com.yourcompany.yourapp"

Event Types

EVENT_IN - Area Entry

Triggered when the user enters an area of interest (monitored Cell ID).

{
"event_type": "EVENT_IN",
"event_duration": -1,
"cell_id": "8881839825fffff",
...
}

Characteristics:

  • event_type: always "EVENT_IN"
  • event_duration: always -1 (no duration yet as the user just entered)

Usage Examples

Example 1: Entry Event (iOS)

{
"mm": 1220290060,
"cell_id": "88a8100ecdfffff",
"event_type": "EVENT_IN",
"event_duration": -1,
"created_at": 1767623650044,
"brand": "apple",
"model": "iPhone15,3",
"cfray": "abc123def456-GRU",
"origin": "beacon",
"adv_key": "com.mango.nexopdf",
"os": "iOS",
"os_version": "17.2",
"package_name": "com.Dataoris.app"
}

Interpretation: A user with an iPhone 15 Pro entered cell 88a8100ecdfffff using the app with package name com.Dataoris.app.

Event Processing

Recommendations

  1. Validation: Always validate the received JSON structure
  2. Idempotency: Use the created_at + mm + event_type field to avoid processing duplicate events
  3. Asynchronous: Return 200 OK immediately and process the event asynchronously
  4. Logging: Log all received events for analysis and debugging

Validation Example (Node.js)

function validateEvent(event) {
const requiredFields = ["mm", "cell_id", "event_type", "created_at"];

for (const field of requiredFields) {
if (!(field in event)) {
throw new Error(`Required field missing: ${field}`);
}
}

return true;
}

Timestamp Conversion

The created_at field is in Unix timestamp format (milliseconds).

JavaScript/Node.js

const date = new Date(event.created_at);
console.log(date.toISOString()); // "2026-01-05T12:34:10.044Z"

Python

from datetime import datetime

timestamp_ms = 1767623650044
date = datetime.fromtimestamp(timestamp_ms / 1000)
print(date.isoformat()) # "2026-01-05T12:34:10.044"

PHP

$timestamp_ms = 1767623650044;
$date = new DateTime('@' . ($timestamp_ms / 1000));
echo $date->format('Y-m-d H:i:s');

Fields that May Vary

Some fields may have different values depending on context:

origin

  • "beacon": Detection via Grouplink IoT
  • "beacon-gps": Detection via Grouplink IoT GPS
  • "gps": Detection via GPS

brand

  • "apple": iOS devices (iPhone, iPad)
  • "samsung": Samsung devices
  • "xiaomi": Xiaomi devices
  • "motorola": Motorola devices
  • Among other Android manufacturers

os

  • "iOS": Apple operating system
  • "Android": Android operating system

Frequently Asked Questions

Is the mm field unique per device?

Yes, mm is a hash of the device ID and represents a specific device in a pseudonymous way.

What to do if I receive duplicate events?

Implement deduplication using the combination of mm + created_at + event_type + cell_id.

Are events sent in real-time?

Yes, events are sent in real-time as soon as detected by the SDK. There may be a latency of a few seconds depending on device connectivity.

How do I know which specific user generated the event?

The mm field is a pseudonymous identifier. If you need to associate it with a specific user in your system, you can implement user identification in the SDK (see SDK documentation).

Next Steps

Support

Questions about event structure? Get in touch: